# -*- coding: UTF-8 -*-
# AoI相关代码 多源-单买家
import copy
from matplotlib import pyplot as plt
from seller_SP import SellerAoISP
from util import Util


def chooseSeller_AoI(S, bindex, budget, T):
    """
    基于边缘AoI单位成本，选择合适的买家
    arg1: S 数据源集合
    arg2: bindex 当前买家编号
    arg3: budget 当前买家预算
    arg4: T 时间范围
    return: sg 被选中的数据源的编号集合
    """
    qseller = len(S)  # 数据源数量
    sg = []  # 被选中的数据源序号
    b = budget  # 剩余预算
    stop = 1  # 终止标记 =1继续 =0停止
    # 迭代选择
    while(stop == 1):
        stop = 0  # 结束条件
        # 寻找未被选中，且价格不大于剩余预算的数据源id
        # 若所有源节点已被选中，或剩余预算不够再选任何一个，则结束
        canChoose = []
        for i in range(qseller):
            if((not i in sg) and (S[i].price[bindex] <= b)):
                stop = 1
                canChoose.append(i)
                S[i].delta = 0
        if(stop == 0):
            break
        maxdelta = -1  # 最大的单位开销AoI降幅
        imaxdelta = -1  # 带来最大单位开销AoI降幅的数据源编号
        # 遍历符合条件的数据源
        for i in canChoose:
            aoi1 = getAoI(S, sg, T)
            stmp = sg+[i]
            aoi2 = getAoI(S, stmp, T)
            S[i].delta = (aoi1-aoi2)/(S[i].price[bindex])
            # 寻找单位开销AoI降幅最大的数据源
            if(S[i].delta > maxdelta):
                maxdelta = S[i].delta
                imaxdelta = i
        # 将单位开销AoI降幅最大的数据源加入已被选择数据源集合中
        sg.append(imaxdelta)
        # 更新剩余预算
        b -= S[imaxdelta].price[bindex]
    sg.sort()
    return sg


def getAoI(sn, sg, T):
    """获取利用已选节点集合sg产生的AoI开销
    """
    update = [0]
    for s in sg:
        update += sn[s].updates
    update.sort()
    update.append(T)
    lset = set(update)  # 用集合确保时间点的唯一性
    update = [x for x in lset]
    update.sort()
    aoi = 0
    last = update[0]
    for i in update:
        d = i-last
        aoi += d**2
        last = i
    aoi = aoi/2 - T/2
    return aoi


if(__name__ == "__main__"):
    # 测试参数
    qseller = 10  # 数据源数量
    qbuyer = 1  # 买家数量
    budget = 120  # 初始预算
    T = 20  # 时间段数量

    # 初始化
    sn = []  # 数据源集合
    for i in range(qseller):
        seller = SellerAoISP(i, qbuyer, T)
        sn.append(seller)

    sg = chooseSeller_AoI(sn, 0, budget, T)
    print("sg:", sg)
